package com.ck.easy.listener;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.exception.ExcelDataConvertException;
import com.ck.common.utils.json.JacksonUtil;
import com.ck.easy.common.entity.SourceEntity;
import com.ck.easy.service.EasyExcelService;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Description:    excel读取监听器
 * @author ck
 */
@Slf4j
public class DefaultExcelListener<T> extends AnalysisEventListener<T> {

    private final List<T> dataList  = new ArrayList();

    private  EasyExcelService easyExcelService;

    public DefaultExcelListener() {
    }
    public DefaultExcelListener(EasyExcelService easyExcelService) {
        this.easyExcelService = easyExcelService;
    }


    /**
     * 读取excel数据前操作(只有不读取表头数据时才会触发此方法)
     */
    @Override
    public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
        log.info("======================================================");
        log.info("解析第一行数据:{}", JacksonUtil.objectToJson(headMap));
        log.info("======================================================");
    }

    /**
     * 读取excel数据操作
     * @param object
     * @param context
     */
    @Override
    public void invoke(T object, AnalysisContext context) {

        dataList.add(object);
        log.info("list容量"+dataList .size()+"---"+object);
         // 实际数据量比较大时，rows里的数据可以存到一定量之后进行批量处理（比如存到数据库），
         // 然后清空列表，以防止内存占用过多造成OOM
        //TODO 待优化 测试时只会读取第一个sheet页的数据，并且如果要将excel的数据入库的话以10w为分界点，第100001条数据以及不满足10w的用什么方式入库
        if (dataList.size() >= 100000) {
            log.info("存入数据库ing");
            savaData();
            //清理集合便于GC回收
            dataList.clear();
            }
        }

    /**
     * 存入数据库
     */
    private void savaData() {
        easyExcelService.importFile((List<SourceEntity>) dataList);
    }

    /**
     * 读取完excel数据后的操作
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        log.info("成功读取【"+ dataList.size()+"】条数据");
    }

    /**
     * 在读取excel异常 获取其他异常下会调用本接口。抛出异常则停止读取。如果这里不抛出异常则 继续读取下一行。
     */
    @Override
    public void onException(Exception exception, AnalysisContext context) {
        log.error("解析失败，但是继续解析下一行:{}", exception.getMessage());
        if (exception instanceof ExcelDataConvertException) {
            ExcelDataConvertException excelDataConvertException = (ExcelDataConvertException)exception;
            log.error("第{}行，第{}列解析异常，数据为:{}", excelDataConvertException.getRowIndex(),
                    excelDataConvertException.getColumnIndex(), excelDataConvertException.getCellData());
        }
    }

    /**
     * @return 返回读取excel总数据
     */
    public List<T> getRows() {
        return dataList;
    }
}
